/* $RCSFile: ADNUrlBuilderHelper.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.UrlBuilderProvider.Implementation/ADNUrlBuilderHelper.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:31  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Diagnostics;
using System.Configuration;
using System.Web;
using System.Collections;
using System.Collections.Generic;
using System.Web.Caching;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.Runtime.Remoting.Contexts;
using System.Text.RegularExpressions;

using AddonNice.Settings;
using AddonNice.Configuration;

using Cache2    =   AddonNice.Settings.Cache.CurrentCache;

namespace AddonNice.Web
{
	/// <summary>
	/// Summary description for Helper.
	/// </summary>
	internal sealed class ADNUrlBuilderHelper
	{
		public const string IsPlaceHolderID     =   "TabPlaceholder"; 
		public const string TabLinkID           =   "TabLink";
		public const string PageNameID          =   "UrlPageName";
		public const string UrlKeywordsID       =   "TabUrlKeyword";

		/// <summary>
		/// Builds up a cache key for Url Elements/Properties
		/// </summary>
		/// <param name="pageID">The ID of the page for which you want to generate a url element cache key for</param>
		/// <param name="UrlElement">The Url element you are after (IsPlaceHolderID/TabLinkID/PageNameID/UrlKeywordsID) constants</param>
		/// <returns>A unique key</returns>
		private static string UrlElementCacheKey(int pageID, string UrlElement)
		{
			//return string.Concat(Portal.UniqueID, pageID, UrlElement);	
			return string.Format("{0}_{1}", pageID, UrlElement);	
		}

		/// <summary>
		/// Clears all cached url elements for a given page
		/// </summary>
		public static void ClearUrlElements(int pageID)
		{
			Cache applicationCache      =   HttpRuntime.Cache;
			
			string placeHolderCacheKey  =   UrlElementCacheKey(pageID, IsPlaceHolderID);
			string tabLinkCacheKey      =   UrlElementCacheKey(pageID, TabLinkID);
			string pageNameCacheKey     =   UrlElementCacheKey(pageID, PageNameID);
			string urlKeywordsCacheKey  =   UrlElementCacheKey(pageID, UrlKeywordsID); 
			
			if( Cache2.Exists(placeHolderCacheKey) )
				Cache2.Remove(placeHolderCacheKey);
			
			if( Cache2.Exists(tabLinkCacheKey) )
				Cache2.Remove(tabLinkCacheKey);
			
			if( Cache2.Exists(pageNameCacheKey) )
				Cache2.Remove(pageNameCacheKey);

			if( Cache2.Exists(urlKeywordsCacheKey) )
				Cache2.Remove(urlKeywordsCacheKey);
		}

		/// <summary>
		/// This method is used to retrieve a specific Url Property
		/// </summary>
		/// <param name="pageID">The ID of the page the Url belongs to</param>
		/// <param name="propertyID">The ID of the property you are interested in</param>
		/// <returns>A string value representing the property you are interested in</returns>
		public static object PageSpecificProperty(int pageID, string propertyID)
		{
			// Page 0 is shared across portals as a default setting (It doesn't have any real data associated with it so return defaults);
			if( pageID == 0 )
			{
				if ( propertyID.ToUpper() == IsPlaceHolderID.ToUpper() )
					return false;
				return string.Empty;
			}

			// get the unique cache key for the property requested
			string uniquePropertyCacheKey   =   UrlElementCacheKey(pageID, propertyID);
			
		
			if ( !Cache2.Exists(uniquePropertyCacheKey) )
			{
				string property             =   string.Empty;
				
				using (SqlConnection conn   =   new SqlConnection(SiteConnectionString))
				{
					try
					{
						// Open the connection
						conn.Open();
                        string strcmd       =   string.Format("SELECT SettingValue FROM dbo.adn_TabSettings WHERE TabID={0} AND SettingName = '{1}'", 
                            pageID, propertyID.ToUpper());
						using (SqlCommand cmd = new SqlCommand(strcmd, conn))
						{
							property        =   (string) cmd.ExecuteScalar();
						}
					}

					catch(Exception ex)
					{
                        if ( ProviderTraceSwitch.Sw.TraceError )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ADNUrlBuilderHelper PageSpecificProperty pageID: {0}, propertyID: {1}, ex: {2}",pageID,propertyID,ex),ProviderTraceSwitch.Sw.Info);
                    }

					finally
					{
						// Close the connection
						if (conn != null)
							conn.Close();
					}
				}
                if ( ProviderTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderHelper PageSpecificProperty pageID: {0}, propertyID: '{1}', Property: '{2}'",pageID,propertyID,property),ProviderTraceSwitch.Sw.Info);

				// if null is returned always ensure that either a bool (if it is a TabPlaceholder) or an empty string is returned.
				if ( string.IsNullOrEmpty(property) )
				{
					// Check to make sure it is not a placeholder...if it is change it to false otherwise ensure that it's value is ""
					if (propertyID.ToUpper() == IsPlaceHolderID.ToUpper())
						property            =   StStr.strFalse;

					else
						property            =   string.Empty;
				}

				else
				{
					// Just check to see that it is cleaned before caching it (i.e. removing illegal characters)
					// If this section grows too much I will clean it up into methods instead of using if else checks.
					if ((propertyID.ToUpper() == PageNameID.ToUpper()) || (propertyID.ToUpper() == UrlKeywordsID.ToUpper()))
					{
						// Replace any illegal characters such as space and special characters and replace it with "-"
						property            =   Regex.Replace(property, @"[^A-Za-z0-9]", "-");
						if ( ( propertyID == PageNameID )  && !propertyID.EndsWith(".aspx",StringComparison.InvariantCultureIgnoreCase) )
							property        +=  ".aspx";
					}
				}
				
                InsertCache(pageID,uniquePropertyCacheKey,property);
				if ( propertyID.ToUpper() == IsPlaceHolderID.ToUpper() )
					return bool.Parse(property);
				return property;
			}
			return Cache2.Get(uniquePropertyCacheKey);
		}

        public static void InsertCache(int pageID,string uniquePropertyCacheKey,object property)
        {
            // dependencies so that if global pages cache key is changed or tabsettings have changed (which means the urlkeyword, tablink or placeholder status has changed) cache is reset
            string[] dependencyKey      =   new String[1];
            dependencyKey[0]            =   AddonNice.Settings.Cache.Key.TabSettings(pageID);
            Cache2.InsertVLong(uniquePropertyCacheKey,property,Cache2.GlobalPagesDependency(dependencyKey));
        }

		/// <summary>
		/// This method is used to get all Url Elements in one go
		/// </summary>
		/// <param name="pageID">The ID of the page you are interested in</param>
		/// <param name="_isPlaceHolder">Is this url a place holder (Not a real url)</param>
		/// <param name="_tabLink">Is this Url a link to an external site/resource</param>
		/// <param name="_urlKeywords">Are there any keywords that should be added to this url</param>
		/// <param name="_pageName">Does this url have a friendly page name other than the default</param>
		public static void GetUrlElements(int pageID, ref bool _isPlaceHolder, ref string _tabLink,ref string _urlKeywords, ref string _pageName)
		{
			// pageID 0 is a default page shared across portals with no real settings
			if( pageID == 0 )
				return;

			string isPlaceHolderKey                 =   UrlElementCacheKey(pageID, IsPlaceHolderID);
			string tabLinkKey                       =   UrlElementCacheKey(pageID, TabLinkID);
			string pageNameKey                      =   UrlElementCacheKey(pageID, PageNameID);
			string urlKeywordsKey                   =   UrlElementCacheKey(pageID, UrlKeywordsID);

			// if any values are null refetch
			if ( !Cache2.Exists(isPlaceHolderKey) || 
                    !Cache2.Exists(tabLinkKey) || 
                    !Cache2.Exists(pageNameKey) ||  
                    !Cache2.Exists(urlKeywordsKey) )
			{
				
                SqlDataReader pageElements          =   null;
                using (SqlConnection conn           =   new SqlConnection(SiteConnectionString))
				{
					try
					{
						// Open the connection
						conn.Open();
                        string strcmd               =   string.Format("SELECT ISNULL((SELECT SettingValue FROM dbo.adn_TabSettings WHERE TabID={3} AND SettingName = '{0}'),'') as PageName,ISNULL((SELECT SettingValue FROM dbo.adn_TabSettings WHERE TabID={3} AND SettingName = '{1}'),'') as Keywords,ISNULL((SELECT SettingValue FROM dbo.adn_TabSettings WHERE TabID={3} AND SettingName = '{2}'),'') as ExternalLink,ISNULL((SELECT SettingValue FROM dbo.adn_TabSettings WHERE TabID={3} AND SettingName = '{4}'),'') as IsPlaceHolder", 
                            new object[] { PageNameID.ToUpper(), UrlKeywordsID.ToUpper(), TabLinkID.ToUpper(), pageID, IsPlaceHolderID.ToUpper() });
						using (SqlCommand cmd       =   new SqlCommand(strcmd, conn))
						{
							// 1. Instantiate a new command above
							// 2. populate values
							pageElements            =   cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
							if( pageElements.HasRows )
							{
								pageElements.Read();

								if( pageElements["PageName"].ToString() != String.Empty)
								{
									_pageName       =   Convert.ToString(pageElements["PageName"]);
									_pageName       =   Regex.Replace(_pageName, @"[^A-Za-z0-9]", "-");
									_pageName       +=  ".aspx";
								    // insert value in cache so it doesn't always try to retrieve it
                                    InsertCache(pageID,pageNameKey,_pageName);
								}
									
								if(pageElements["Keywords"].ToString() != String.Empty)
								{
									_urlKeywords    =   Convert.ToString(pageElements["Keywords"]);
									_urlKeywords    =   Regex.Replace(_urlKeywords, @"[^A-Za-z0-9]", "-");
								    // insert value in cache so it doesn't always try to retrieve it
                                    InsertCache(pageID,urlKeywordsKey, _urlKeywords);
								}

								if(pageElements["ExternalLink"].ToString()!= String.Empty)
								{
									_tabLink        =   Convert.ToString(pageElements["ExternalLink"]);
								    // insert value in cache so it doesn't always try to retrieve it
                                    InsertCache(pageID,tabLinkKey, _tabLink);
								}

								if(pageElements["IsPlaceHolder"].ToString() != String.Empty)
								{
									_isPlaceHolder  =   bool.Parse(pageElements["IsPlaceHolder"].ToString());
								    // insert value in cache so it doesn't always try to retrieve it
                                    InsertCache(pageID,isPlaceHolderKey, _isPlaceHolder);
								}
							}
						}
					}
					catch(Exception ex)
					{
                        if ( ProviderTraceSwitch.Sw.TraceError )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ADNUrlBuilderHelper GetUrlElements pageID:{0}, ex:{1}", pageID, ex),ProviderTraceSwitch.Sw.Info);
                    }

					finally
					{
					    // close the reader
                        if ( pageElements != null )
							pageElements.Close();
						// Close the connection
						if (conn != null)
							conn.Close();
					}
				}
			}
			else
			{
				// if cached value is empty string then leave it as default
				if( Cache2.Exists(pageNameKey) )
					_pageName                       =   (string)Cache2.Get(pageNameKey);
				_urlKeywords                        =   Cache2.Exists(urlKeywordsKey) ? (string)Cache2.Get(urlKeywordsKey):string.Empty;
				_tabLink                            =   Cache2.Exists(tabLinkKey) ? (string)Cache2.Get(tabLinkKey):string.Empty;
				_isPlaceHolder                      =   Cache2.Exists(isPlaceHolderKey) ? (bool)Cache2.Get(isPlaceHolderKey):false;
			}
		}
		

		/// <summary>
		/// ApplicationPath, Application dependent relative Application Path.
		/// Base dir for all portal code
		/// Since it is common for all portals is declared as static
		/// </summary>
		public static string ApplicationPath
		{
			get
			{
				return Path.ApplicationRoot;
			}
		}

		/// <summary>
		/// Returns the current site's database connection string
		/// </summary>
		private static string SiteConnectionString
		{
			get
			{
				return Config.ConnectionString;
			}
        }


        #region  Addon Nice Extensions


        public static bool PortalIsSecured
		{
			get
			{
				Dictionary<string,string> CustomSettings = GetPortalCustomSettings();
                if (CustomSettings.ContainsKey(StStr.SiteSettingsPortalIsSecured) )
                    return bool.Parse(CustomSettings[StStr.SiteSettingsPortalIsSecured]);
				return false;
			}
		}
		
		public static string[] PortalSecuredDirs
		{
			get
			{
				Dictionary<string,string> CustomSettings = GetPortalCustomSettings();
                if (CustomSettings.ContainsKey(StStr.SiteSettingsPortalSecuredDirs))
				{
					string str	=	CustomSettings[StStr.SiteSettingsPortalSecuredDirs];
					return str.Split(new char[]{';'},StringSplitOptions.RemoveEmptyEntries);
				}
				return new string[0];
			}
		}

		public static Dictionary<string,string> GetPortalCustomSettings()
		{
            string cacheKey =   AddonNice.Settings.Cache.Key.BuilderPortalSettings(Portal.UniqueID);
            int portalID    =   -1;
            if ( AddonNice.Settings.Cache.CurrentCache.Exists(cacheKey) )
            {
                portalID    =   (int)AddonNice.Settings.Cache.CurrentCache.Get(cacheKey);
            }
            else
            {
                portalID    =   GetPortalFromAlias(Portal.UniqueID);
                AddonNice.Settings.Cache.CurrentCache.InsertLong(cacheKey,portalID);
            }
			return GetPortalCustomSettings(portalID);
		}

        public static int GetPortalFromAlias(string portalAlias)
		{
			if ( ProviderTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderHelper GetPortalFromAlias BEG PortalAlias: {0}.",portalAlias),ProviderTraceSwitch.Sw.Info);
			SqlConnection myConnection	        =   new SqlConnection(Config.ConnectionString);
			SqlCommand myCommand		        =   new SqlCommand("dbo.adn_GetPortalFromAlias", myConnection);
            myCommand.CommandType			    =   CommandType.StoredProcedure;

            SqlParameter parameterPortalAlias	=   new SqlParameter(StStr.ATPortalAlias, SqlDbType.NVarChar, 128);
            parameterPortalAlias.Value			=   portalAlias;
            myCommand.Parameters.Add(parameterPortalAlias);

            SqlParameter retParam               =   new SqlParameter(StStr.ATReturnValue, SqlDbType.Int); 
            retParam.Direction                  =   ParameterDirection.ReturnValue;
            myCommand.Parameters.Add(retParam);

            int portalID                        =   -1;
            try
			{
                myConnection.Open();
				myCommand.ExecuteNonQuery();
                portalID                        =   (int)retParam.Value;
			}
			catch(Exception exp)
			{
				if ( ProviderTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ADNUrlBuilderHelper GetPortalFromAlias PortalAlias: {0}, ex: {1}",portalAlias,exp),ProviderTraceSwitch.Sw.Info);
                throw;
			}
            finally
            {
                if (myConnection.State == System.Data.ConnectionState.Open)
                    myConnection.Close();
            }
			if ( ProviderTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderHelper GetPortalFromAlias END PortalAlias: {0}, portalID: {1}.",portalAlias,portalID),ProviderTraceSwitch.Sw.Info);
            return portalID;
        }

        public static Dictionary<string,string> GetPortalCustomSettings(int portalID)
		{
            Dictionary<string,string> _settings =   new Dictionary<string,string>();
            string cacheKey                     =   AddonNice.Settings.Cache.Key.BuilderPortalSettings(portalID);
			if( !Cache2.Exists(cacheKey) )
			{
				// Get Settings for this Portal from the database
				SqlConnection myConnection	    =   new SqlConnection(Config.ConnectionString);
				SqlCommand myCommand		    =   new SqlCommand("dbo.adn_GetPortalCustomSettings", myConnection);

				myCommand.CommandType		    =   CommandType.StoredProcedure;

				SqlParameter parameterPortalID  =   new SqlParameter(StStr.ATPortalID, SqlDbType.Int, 4);
				parameterPortalID.Value		    =   portalID;
				myCommand.Parameters.Add(parameterPortalID);

				SqlDataReader dr		        =	null;
				try
				{
					myConnection.Open();
					dr					        =   myCommand.ExecuteReader(CommandBehavior.CloseConnection);
					while (dr.Read()) 
					{
                        string key              =   (string)dr[StStr.DBSettingName];
                        if (string.IsNullOrEmpty(key))
                            continue;
                        string val              =   (string)dr[StStr.DBSettingValue];
                        if (string.IsNullOrEmpty(val))
                            continue;
                        string k                =   key.ToUpper();
                        if (!_settings.ContainsKey(k))
                            _settings.Add(k,val);
					}
                    Cache2.InsertLong(cacheKey, _settings);
				}
				catch(Exception ex)
				{
					if ( ProviderTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ADNUrlBuilderHelper GetPortalCustomSettings PortalID:{0}, ex: {1}",portalID,ex),ProviderTraceSwitch.Sw.Info);
                    throw;
				}
				finally
				{
					if ( dr != null && !dr.IsClosed )
						dr.Close();
					if ( myConnection.State == System.Data.ConnectionState.Open )
						myConnection.Close();
				}
				if ( ProviderTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderHelper GetPortalCustomSettings PortalID:{0}, Count: {1}",portalID,_settings.Count),ProviderTraceSwitch.Sw.Info);
			}
			else
			{
                _settings                       =   (Dictionary<string,string>)Cache2.Get(cacheKey);
			}
			return _settings;
		}
        		
		public static string ApplicationFullPath
		{
			get 
			{
				return AddonNice.Settings.Path.ApplicationFullPath;
			}
		}
        
        #endregion  
    }
}
